library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity pu is
    Port ( clk : in  STD_LOGIC;
           rst : in  STD_LOGIC;
			  REN, RWE, ROE : out std_logic;
				RA : out std_logic_vector (17 downto 0);
				RD : inout std_logic_vector (15 downto 0);
           sw : in  STD_LOGIC_VECTOR (15 downto 0);
			  seg : out  STD_LOGIC_VECTOR (6 downto 0);
           led : out  STD_LOGIC_VECTOR (15 downto 0));
end pu;

architecture Behavioral of pu is
signal cnt:   STD_LOGIC_VECTOR (2 downto 0):="001";
begin

process(clk)
variable tem	:  STD_LOGIC_VECTOR (15 downto 0):="0000000000000000";
variable op	:  STD_LOGIC_VECTOR (4 downto 0):="00000";
variable tem3_x	:  STD_LOGIC_VECTOR (2 downto 0):="000";
variable tem3_y	:  STD_LOGIC_VECTOR (2 downto 0):="000";
variable tem3_z	:  STD_LOGIC_VECTOR (2 downto 0):="000";
variable tem3_imm	:  STD_LOGIC_VECTOR (2 downto 0):="000";

variable tem8	:  STD_LOGIC_VECTOR (7 downto 0):="00000000";
variable tem16	:  STD_LOGIC_VECTOR (15 downto 0):="0000000000000000";

variable R1	:  STD_LOGIC_VECTOR (15 downto 0):="0000000000000000";
variable R2	:  STD_LOGIC_VECTOR (15 downto 0):="0000000000000000";
variable R3	:  STD_LOGIC_VECTOR (15 downto 0):="0000000000000000";
variable R4	:  STD_LOGIC_VECTOR (15 downto 0):="0000000000000000";
variable R5	:  STD_LOGIC_VECTOR (15 downto 0):="0000000000000000";
variable R6	:  STD_LOGIC_VECTOR (15 downto 0):="0000000000000000";
variable R7	:  STD_LOGIC_VECTOR (15 downto 0):="0000000000000000";
variable R0	:  STD_LOGIC_VECTOR (15 downto 0):="0000000000000000";
variable T	:  STD_LOGIC;

variable data	:  STD_LOGIC_VECTOR (15 downto 0):="0000000000000000";


variable alua :STD_LOGIC_VECTOR (15 downto 0):="0000000000000000";
variable alub :STD_LOGIC_VECTOR (15 downto 0):="0000000000000000";
variable aluc :STD_LOGIC_VECTOR (15 downto 0):="0000000000000000";

begin
	if(clk'event and clk='1') then  
		if(cnt="001") then --取指
			RD<="ZZZZZZZZZZZZZZZZ";
			--RA<="00" & pc;
			REN<='0';
			ROE<='0';
			RWE<='1';
			
			seg<=not"1111001";--1
			tem:=sw;
			cnt<="010";
		end if;
		if(cnt="010") then---译码
			seg<=not"0100100";--2
			op:=tem(15 downto 11);--OP
				if(op = "01001") then  
					tem3_x:=tem(10 downto 8);--寄存器
						case tem3_x is
					when "000" =>
					 alua := R0;
					when "001" =>
					 alua := R1;
					when "010" =>
					 alua := R2;
					when "011" =>
					 alua := R3;
					when "100" =>
					 alua := R4;
					when "101" =>
					 alua := R5;
					when "110" =>
					 alua := R6;
					when "111" =>
					 alua := R7;
					when others =>
					 NULL;
					end case;

					tem8:=tem(7 downto 0); --立即数
					alub:= "00000000" & tem8;
				end if;
				if(op = "01010") then  
					tem3_x:=tem(10 downto 8);--寄存器
						case tem3_x is
					when "000" =>
					 alua := R0;
					when "001" =>
					 alua := R1;
					when "010" =>
					 alua := R2;
					when "011" =>
					 alua := R3;
					when "100" =>
					 alua := R4;
					when "101" =>
					 alua := R5;
					when "110" =>
					 alua := R6;
					when "111" =>
					 alua := R7;
					when others =>
					 NULL;
					end case;

					tem8:=tem(7 downto 0); --立即数
					alub:= "00000000" & tem8;
				end if;
				if(op = "00110") then  
					tem3_y:=tem(7 downto 5);--寄存器
						case tem3_y is
					when "000" =>
					 alub := R0;
					when "001" =>
					 alub := R1;
					when "010" =>
					 alub := R2;
					when "011" =>
					 alub := R3;
					when "100" =>
					 alub := R4;
					when "101" =>
					 alub := R5;
					when "110" =>
					 alub := R6;
					when "111" =>
					 alub := R7;
					when others =>
					 NULL;
					end case;

					tem3_x:=tem(10 downto 8); --寄存器
					tem3_imm:=tem(4 downto 2); --立即数
				end if;
				if(op = "01101") then  
					tem3_x:=tem(10 downto 8);--寄存器
						case tem3_x is
					when "000" =>
					 alua := R0;
					when "001" =>
					 alua := R1;
					when "010" =>
					 alua := R2;
					when "011" =>
					 alua := R3;
					when "100" =>
					 alua := R4;
					when "101" =>
					 alua := R5;
					when "110" =>
					 alua := R6;
					when "111" =>
					 alua := R7;
					when others =>
					 NULL;
					end case;

					tem8:=tem(7 downto 0); --立即数
					alub:= "00000000" & tem8;
				end if;
				if(op = "01100") then
					tem8:=tem(7 downto 0); --立即数
					alub:= "00000000" & tem8;
				end if;
				if(op = "11100") then  
					tem3_x:=tem(10 downto 8);--寄存器
						case tem3_x is
					when "000" =>
					 alua := R0;
					when "001" =>
					 alua := R1;
					when "010" =>
					 alua := R2;
					when "011" =>
					 alua := R3;
					when "100" =>
					 alua := R4;
					when "101" =>
					 alua := R5;
					when "110" =>
					 alua := R6;
					when "111" =>
					 alua := R7;
					when others =>
					 NULL;
					end case;

					tem3_y:=tem(7 downto 5);--寄存器
						case tem3_y is
					when "000" =>
					 alub := R0;
					when "001" =>
					 alub := R1;
					when "010" =>
					 alub := R2;
					when "011" =>
					 alub := R3;
					when "100" =>
					 alub := R4;
					when "101" =>
					 alub := R5;
					when "110" =>
					 alub := R6;
					when "111" =>
					 alub := R7;
					when others =>
					 NULL;
					end case;

					tem3_z:=tem(4 downto 2);--寄存器
				end if;
				if(op = "11101") then  
					tem3_x:=tem(10 downto 8);--寄存器
						case tem3_x is
					when "000" =>
					 alua := R0;
					when "001" =>
					 alua := R1;
					when "010" =>
					 alua := R2;
					when "011" =>
					 alua := R3;
					when "100" =>
					 alua := R4;
					when "101" =>
					 alua := R5;
					when "110" =>
					 alua := R6;
					when "111" =>
					 alua := R7;
					when others =>
					 NULL;
					end case;

					tem3_y:=tem(7 downto 5);--寄存器
						case tem3_y is
					when "000" =>
					 alub := R0;
					when "001" =>
					 alub := R1;
					when "010" =>
					 alub := R2;
					when "011" =>
					 alub := R3;
					when "100" =>
					 alub := R4;
					when "101" =>
					 alub := R5;
					when "110" =>
					 alub := R6;
					when "111" =>
					 alub := R7;
					when others =>
					 NULL;
					end case;
				end if;
				if(op = "11011") then  
					tem3_x:=tem(10 downto 8);--寄存器
								case tem3_x is
							when "000" =>
							alua := R0;
							when "001" =>
							 alua := R1;
							when "010" =>
							 alua := R2;
							when "011" =>
							 alua:= R3;
							when "100" =>
							 alua := R4;
							when "101" =>
							 alua := R5;
							when "110" =>
							 alua := R6;
							when "111" =>
							 alua := R7;
							when others =>
							 NULL;
					end case;



					tem3_y:=tem(7 downto 5);--寄存器
						case tem3_y is
							when "000" =>
							 data := R0;
							when "001" =>
							 data := R1;
							when "010" =>
							 data := R2;
							when "011" =>
							 data := R3;
							when "100" =>
							 data := R4;
							when "101" =>
							 data := R5;
							when "110" =>
							 data := R6;
							when "111" =>
							 data := R7;
							when others =>
							 NULL;
					end case;

					tem8:=tem(7 downto 0); --立即数
					alub:= "00000000" & tem8;
				end if;
				if(op = "10011") then  
				tem3_x:=tem(10 downto 8);--寄存器
					case tem3_x is
							when "000" =>
							alua := R0;
							when "001" =>
							 alua := R1;
							when "010" =>
							 alua := R2;
							when "011" =>
							 alua:= R3;
							when "100" =>
							 alua := R4;
							when "101" =>
							 alua := R5;
							when "110" =>
							 alua := R6;
							when "111" =>
							 alua := R7;
							when others =>
							 NULL;
					end case;
				end if;
		cnt<="011";
		end if;
		if(cnt="011") then-----执行
			seg<=not"0110000";--3
			if(op = "01001") then  
				aluc:= alua+alub;
			end if;
			if(op = "11101") then  
				aluc:= alua-alub;
			end if;
			if(op = "01010") then  
				aluc:= alua-alub;
			end if;
			if(op = "00110") then  
				if tem3_imm = X"0000" then
					aluc := to_stdlogicvector(to_bitvector(alub) sll 8);
				else  
					aluc := to_stdlogicvector(to_bitvector(alub) sll conv_integer(tem3_imm));
				end if;
			end if;
			if(op = "01101") then  
				aluc:=alub;
			end if;
			if(op = "11100") then  
				aluc:= alua+alub;
			end if;
			if(op = "11011") then  
				aluc:=alua+"00000000000" & tem(4 downto 0);
				RA<="00" & aluc;
                
			REN<='0';
			ROE<='0';
			RWE<='1';

			end if;
			if(op = "10011") then  
				aluc:=alua+"00000000000" & tem(4 downto 0);
				RA<="00" & aluc;

			end if;
		cnt<="100";
		end if;
		if(cnt="100") then----访存
			seg<=not"0011001";--4
		if(op = "11011") then
			RD<=data;
			REN<='0';
			ROE<='1';
			RWE<='0';
	
		end if;
			cnt<="101";
		end if;
		if(cnt="101") then----xiehui
			seg<=not"0010010";--5
			
           -- pc<=pc+"1";
		if(op = "11011") then
			REN<='0';
			ROE<='0';
			RWE<='1';
	
		end if;
		if(op = "10011") then
				tem3_y:=tem(7 downto 5);--寄存器
						case tem3_y is
							when "000" =>
							R0:=RD;
							when "001" =>
							R1:=RD;
							when "010" =>
							 R2:=RD;
							when "011" =>
							R3:=RD;
							when "100" =>
							 R4:=RD;
							when "101" =>
							 R5:=RD;
							when "110" =>
							R6:=RD;
							when "111" =>
							 R7:=RD;
							when others =>
							 NULL;
					end case;
				led<=RD;
		end if;
			if(op = "01001") then
				case tem3_x is
					when "000" =>
						R0 := aluc;
					when "001" =>
						R1 := aluc;
					when "010" =>
						R2 := aluc;
					when "011" =>
						R3 := aluc;
					when "100" =>
						R4 := aluc;
					when "101" =>
						R5 := aluc;
					when "110" =>
						R6 := aluc;
					when "111" =>
						R7 := aluc;
					when others =>
						NULL;
					end case;
				led<=aluc;
			end if;
			if(op = "11101") then
			      if(aluc(15)='1')then
					T:='1';
					else
					T:='0';
               end if;      
				led<="000000000000001" & T;
			end if;
			if(op = "01010") then
			      if(aluc(15)='1')then
					T:='1';
					else
					T:='0';
               end if;      
				led<="000000000000001" & T;
			end if;
			if(op = "00110") then
				case tem3_x is
					when "000" =>
						R0 := aluc;
					when "001" =>
						R1 := aluc;
					when "010" =>
						R2 := aluc;
					when "011" =>
						R3 := aluc;
					when "100" =>
						R4 := aluc;
					when "101" =>
						R5 := aluc;
					when "110" =>
						R6 := aluc;
					when "111" =>
						R7 := aluc;
					when others =>
						NULL;
					end case;
				led<=aluc;
			end if;
			if(op = "01101") then
				case tem3_x is
					when "000" =>
						R0 := aluc;
					when "001" =>
						R1 := aluc;
					when "010" =>
						R2 := aluc;
					when "011" =>
						R3 := aluc;
					when "100" =>
						R4 := aluc;
					when "101" =>
						R5 := aluc;
					when "110" =>
						R6 := aluc;
					when "111" =>
						R7 := aluc;
					when others =>
						NULL;
					end case;
				led<=aluc;
			end if;
			if(op = "11100") then
				case tem3_z is
					when "000" =>
						R0 := aluc;
					when "001" =>
						R1 := aluc;
					when "010" =>
						R2 := aluc;
					when "011" =>
						R3 := aluc;
					when "100" =>
						R4 := aluc;
					when "101" =>
						R5 := aluc;
					when "110" =>
						R6 := aluc;
					when "111" =>
						R7 := aluc;
					when others =>
						NULL;
					end case;
				led<=aluc;
			end if;
	cnt<="001";
		end if;
end if;
end process;
end Behavioral;